home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / cc / sprite / out-sparc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-07  |  52.1 KB  |  1,968 lines

  1. /* Subroutines for insn-output.c for Sun SPARC.
  2.    Copyright (C) 1987, 1988, 1989 Free Software Foundation, Inc.
  3.    Contributed by Michael Tiemann (tiemann@mcc.com)
  4.  
  5. This file is part of GNU CC.
  6.  
  7. GNU CC is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 1, or (at your option)
  10. any later version.
  11.  
  12. GNU CC is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. /* Global variables for machine-dependend things.  */
  22.  
  23. /* This should go away if we pass floats to regs via
  24.    the stack instead of the frame, and if we learn how
  25.    to renumber all the registers when we don't do a save (hard!).  */
  26. extern int frame_pointer_needed;
  27.  
  28. static rtx find_addr_reg ();
  29.  
  30. rtx next_real_insn_no_labels ();
  31.  
  32. /* Return non-zero only if OP is a register of mode MODE,
  33.    or const0_rtx.  */
  34. int
  35. reg_or_0_operand (op, mode)
  36.      rtx op;
  37.      enum machine_mode mode;
  38. {
  39.   return (op == const0_rtx || register_operand (op, mode));
  40. }
  41.  
  42. /* Return non-zero if this pattern, can be evaluated safely, even if it
  43.    was not asked for.  */
  44. int
  45. safe_insn_src_p (op, mode)
  46.      rtx op;
  47.      enum machine_mode mode;
  48. {
  49.   /* Just experimenting.  */
  50.  
  51.   /* No floating point src is safe if it contains an arithmetic
  52.      operation, since that operation may trap.  */
  53.   switch (GET_CODE (op))
  54.     {
  55.     case CONST_INT:
  56.     case LABEL_REF:
  57.     case SYMBOL_REF:
  58.     case CONST:
  59.       return 1;
  60.  
  61.     case REG:
  62.       return 1;
  63.  
  64.     case MEM:
  65.       return CONSTANT_ADDRESS_P (XEXP (op, 0));
  66.  
  67.       /* We never need to negate or complement constants.  */
  68.     case NEG:
  69.       return (mode != SFmode && mode != DFmode);
  70.     case NOT:
  71.       return 1;
  72.  
  73.     case COMPARE:
  74.     case MINUS:
  75.     case PLUS:
  76.       return (mode != SFmode && mode != DFmode);
  77.     case AND:
  78.     case IOR:
  79.     case XOR:
  80.     case LSHIFT:
  81.     case ASHIFT:
  82.     case ASHIFTRT:
  83.     case LSHIFTRT:
  84.       if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
  85.       || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
  86.     return 0;
  87.       return 1;
  88.  
  89.     default:
  90.       return 0;
  91.     }
  92. }
  93.  
  94. /* Return 1 if REG is clobbered in IN.
  95.    Return 0 if REG is used in IN (other than being clobbered).
  96.    Return 2 if REG does not appear in IN.  */
  97.  
  98. static int
  99. reg_clobbered_p (reg, in)
  100.      rtx reg;
  101.      rtx in;
  102. {
  103.   register char *fmt;
  104.   register int i, result = 0;
  105.  
  106.   register enum rtx_code code;
  107.  
  108.   if (in == 0)
  109.     return 2;
  110.  
  111.   code = GET_CODE (in);
  112.  
  113.   switch (code)
  114.     {
  115.       /* Let these fail out quickly.  */
  116.     case CONST_INT:
  117.     case SYMBOL_REF:
  118.     case CONST:
  119.       return 2;
  120.  
  121.     case SUBREG:
  122.       if (SUBREG_WORD (in) != 0)
  123.     in = gen_rtx (REG, SImode, REGNO (SUBREG_REG (in)) + SUBREG_WORD (in));
  124.       else
  125.     in = SUBREG_REG (in);
  126.  
  127.     case REG:
  128.       if (in == reg
  129.       || refers_to_regno_p (REGNO (reg),
  130.                 REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  131.                 in, 0))
  132.     return 0;
  133.       return 2;
  134.  
  135.     case SET:
  136.       if (SET_SRC (in) == reg
  137.       || refers_to_regno_p (REGNO (reg),
  138.                 REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  139.                 SET_SRC (in), 0))
  140.     return 0;
  141.  
  142.       if (SET_DEST (in) == reg)
  143.     return 1;
  144.  
  145.       if (refers_to_regno_p (REGNO (reg),
  146.                  REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  147.                  SET_DEST (in), 0))
  148.     if (GET_CODE (SET_DEST (in)) == REG
  149.         || GET_CODE (SET_DEST (in)) == SUBREG)
  150.       return 1;
  151.     else
  152.       return 0;
  153.       return 2;
  154.  
  155.     case USE:
  156.       if (XEXP (in, 0) == reg
  157.       || refers_to_regno_p (REGNO (reg),
  158.                 REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  159.                 XEXP (in, 0), 0))
  160.     return 0;
  161.       return 2;
  162.  
  163.     case CLOBBER:
  164.       if (XEXP (in, 0) == reg)
  165.     return 1;
  166.       /* If the CLOBBER expression is a SUBREG, accept that as a
  167.      clobber.  But if it is some expression based on this register,
  168.      that is like a USE as far as this register is concerned,
  169.      so we won't take it.  */
  170.       if (refers_to_regno_p (REGNO (reg),
  171.                  REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  172.                  XEXP (in, 0), 0))
  173.     if (GET_CODE (XEXP (in, 0)) == REG
  174.         || GET_CODE (XEXP (in, 0)) == SUBREG)
  175.       return 1;
  176.     else
  177.       return 0;
  178.       return 2;
  179.     }
  180.  
  181.   fmt = GET_RTX_FORMAT (code);
  182.  
  183.   result = 2;
  184.  
  185.   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
  186.     {
  187.       if (fmt[i] == 'E')
  188.     {
  189.       register int j;
  190.       for (j = XVECLEN (in, i) - 1; j >= 0; j--)
  191.         switch (reg_clobbered_p (reg, XVECEXP (in, i, j)))
  192.           {
  193.           case 0:
  194.         return 0;
  195.           case 2:
  196.         continue;
  197.           case 1:
  198.         result = 1;
  199.         break;
  200.           }
  201.     }
  202.       else if (fmt[i] == 'e')
  203.     switch (reg_clobbered_p (reg, XEXP (in, i)))
  204.       {
  205.       case 0:
  206.         return 0;
  207.       case 2:
  208.         continue;
  209.       case 1:
  210.         result = 1;
  211.         break;
  212.       }
  213.     }
  214.   return result;
  215. }
  216.  
  217. /* Return non-zero if OP can be written to without screwing up
  218.    GCC's model of what's going on.  It is assumed that this operand
  219.    appears in the dest position of a SET insn in a conditional
  220.    branch's delay slot.  AFTER is the label to start looking from.  */
  221. int
  222. operand_clobbered_before_used_after (op, after)
  223.      rtx op;
  224.      rtx after;
  225. {
  226.   extern char call_used_regs[];
  227.  
  228.   /* Just experimenting.  */
  229.   if (GET_CODE (op) == CC0)
  230.     return 1;
  231.   if (GET_CODE (op) == REG)
  232.     {
  233.       rtx insn;
  234.  
  235.       if (op == stack_pointer_rtx)
  236.     return 0;
  237.  
  238.       for (insn = NEXT_INSN (after); insn; insn = NEXT_INSN (insn))
  239.     {
  240.       if (GET_CODE (insn) == NOTE)
  241.         continue;
  242.       if (GET_CODE (insn) == INSN
  243.           || GET_CODE (insn) == JUMP_INSN
  244.           || GET_CODE (insn) == CALL_INSN)
  245.         {
  246.           switch (reg_clobbered_p (op, PATTERN (insn)))
  247.         {
  248.         case 0:
  249.           return 0;
  250.         case 2:
  251.           break;
  252.         case 1:
  253.           return 1;
  254.         }
  255.           if (dead_or_set_p (insn, op))
  256.         return 1;
  257.         }
  258.       else if (GET_CODE (insn) == CODE_LABEL)
  259.         return 0;
  260.       if (GET_CODE (insn) == JUMP_INSN)
  261.         {
  262.           if (condjump_p (insn))
  263.         return 0;
  264.           /* This is a jump insn which has already
  265.          been mangled.  We can't tell what it does.  */
  266.           if (GET_CODE (PATTERN (insn)) == PARALLEL)
  267.         return 0;
  268.           if (! JUMP_LABEL (insn))
  269.         return 0;
  270.           /* Keep following jumps.  */
  271.           insn = JUMP_LABEL (insn);
  272.         }
  273.     }
  274.       return 1;
  275.     }
  276.  
  277.   /* In both of these cases, the first insn executed
  278.      for this op will be a sethi %hi(whatever),%g1,
  279.      which is tolerable.  */
  280.   if (GET_CODE (op) == MEM)
  281.     return (CONSTANT_ADDRESS_P (XEXP (op, 0)));
  282.  
  283.   return 0;
  284. }
  285.  
  286. /* Return non-zero if this pattern, as a source to a "SET",
  287.    is known to yield an instruction of unit size.  */
  288. int
  289. single_insn_src_p (op, mode)
  290.      rtx op;
  291.      enum machine_mode mode;
  292. {
  293.   switch (GET_CODE (op))
  294.     {
  295.     case CONST_INT:
  296. #if 1
  297.       /* This is not always a single insn src, technically,
  298.      but output_delayed_branch knows how to deal with it.  */
  299.       return 1;
  300. #else
  301.       if (SMALL_INT (op))
  302.     return 1;
  303.       /* We can put this set insn into delay slot, because this is one
  304.      insn; 'sethi'.  */
  305.       if ((INTVAL (op) & 0x3ff) == 0)
  306.     return 1;
  307.  
  308.       /* This is not a single insn src, technically,
  309.      but output_delayed_branch knows how to deal with it.  */
  310.       return 1;
  311. #endif
  312.  
  313. #if 1
  314.     case SYMBOL_REF:
  315.       /* This is not a single insn src, technically,
  316.      but output_delayed_branch knows how to deal with it.  */
  317.       return 1;
  318. #else
  319.       return 0;
  320. #endif
  321.  
  322.     case REG:
  323.       return 1;
  324.  
  325.     case MEM:
  326. #if 0
  327.       /* This is not a single insn src, technically,
  328.      but output_delayed_branch knows how to deal with it.  */
  329.       if (GET_CODE (XEXP (op, 0)) == SYMBOL_REF)
  330.     return 0;
  331. #endif
  332.       return 1;
  333.  
  334.       /* We never need to negate or complement constants.  */
  335.     case NEG:
  336.       return (mode != DFmode);
  337.     case NOT:
  338.       return 1;
  339.  
  340.     case COMPARE:
  341.     case MINUS:
  342.       /* If the target is cc0, then these insns will take
  343.      two insns (one being a nop).  */
  344.       return (mode != SFmode && mode != DFmode);
  345.     case PLUS:
  346.     case AND:
  347.     case IOR:
  348.     case XOR:
  349.     case LSHIFT:
  350.     case ASHIFT:
  351.     case ASHIFTRT:
  352.     case LSHIFTRT:
  353.       if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
  354.       || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
  355.     return 0;
  356.       return 1;
  357.  
  358.     case SUBREG:
  359.       if (SUBREG_WORD (op) != 0)
  360.     return 0;
  361.       return single_insn_src_p (SUBREG_REG (op), mode);
  362.  
  363.     case SIGN_EXTEND:
  364.     case ZERO_EXTEND:
  365.       /* Lazy... could check for more cases.  */
  366.       if (GET_CODE (XEXP (op, 0)) == MEM
  367.       && ! CONSTANT_ADDRESS_P (XEXP (XEXP (op, 0), 0)))
  368.     return 1;
  369.       return 0;
  370.  
  371.       /* Not doing floating point, since they probably
  372.      take longer than the branch slot they might fill.  */
  373.     case FLOAT_EXTEND:
  374.     case FLOAT_TRUNCATE:
  375.     case FLOAT:
  376.     case FIX:
  377.     case UNSIGNED_FLOAT:
  378.     case UNSIGNED_FIX:
  379.       return 0;
  380.  
  381.     default:
  382.       return 0;
  383.     }
  384. }
  385.  
  386. /* Nonzero only if this *really* is a single insn operand.  */
  387. int
  388. strict_single_insn_op_p (op, mode)
  389.      rtx op;
  390.      enum machine_mode mode;
  391. {
  392.   if (mode == VOIDmode)
  393.     mode = GET_MODE (op);
  394.  
  395.   switch (GET_CODE (op))
  396.     {
  397.     case CC0:
  398.       return 1;
  399.  
  400.     case CONST_INT:
  401.       if (SMALL_INT (op))
  402.     return 1;
  403.       /* We can put this set insn into delay slot, because this is one
  404.      insn; 'sethi'.  */
  405.       if ((INTVAL (op) & 0x3ff) == 0)
  406.     return 1;
  407.       return 0;
  408.  
  409.     case SYMBOL_REF:
  410.       return 0;
  411.  
  412.     case REG:
  413.       return (mode != DFmode && mode != DImode);
  414.  
  415.     case MEM:
  416.       if (! CONSTANT_ADDRESS_P (XEXP (op, 0)))
  417.     return (mode != DFmode && mode != DImode);
  418.       return 0;
  419.  
  420.       /* We never need to negate or complement constants.  */
  421.     case NEG:
  422.       return (mode != DFmode);
  423.     case NOT:
  424.       return 1;
  425.  
  426.     case COMPARE:
  427.     case MINUS:
  428.       /* If the target is cc0, then these insns will take
  429.      two insns (one being a nop).  */
  430.       return (mode != SFmode && mode != DFmode);
  431.     case PLUS:
  432.     case AND:
  433.     case IOR:
  434.     case XOR:
  435.     case LSHIFT:
  436.     case ASHIFT:
  437.     case ASHIFTRT:
  438.     case LSHIFTRT:
  439.       if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
  440.       || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
  441.     return 0;
  442.       return 1;
  443.  
  444.     case SUBREG:
  445.       if (SUBREG_WORD (op) != 0)
  446.     return 0;
  447.       return strict_single_insn_op_p (SUBREG_REG (op), mode);
  448.  
  449.     case SIGN_EXTEND:
  450.     case ZERO_EXTEND:
  451.       if (GET_CODE (XEXP (op, 0)) == MEM
  452.       && ! CONSTANT_ADDRESS_P (XEXP (XEXP (op, 0), 0)))
  453.     return 1;
  454.       return 0;
  455.  
  456.       /* Not doing floating point, since they probably
  457.      take longer than the branch slot they might fill.  */
  458.     case FLOAT_EXTEND:
  459.     case FLOAT_TRUNCATE:
  460.     case FLOAT:
  461.     case FIX:
  462.     case UNSIGNED_FLOAT:
  463.     case UNSIGNED_FIX:
  464.       return 0;
  465.  
  466.     default:
  467.       return 0;
  468.     }
  469. }
  470.  
  471. /* Return truth value of whether OP is a relational operator.  */
  472. int
  473. relop (op, mode)
  474.      rtx op;
  475.      enum machine_mode mode;
  476. {
  477.   switch (GET_CODE (op))
  478.     {
  479.     case EQ:
  480.     case NE:
  481.     case GT:
  482.     case GE:
  483.     case LT:
  484.     case LE:
  485.     case GTU:
  486.     case GEU:
  487.     case LTU:
  488.     case LEU:
  489.       return 1;
  490.     }
  491.   return 0;
  492. }
  493.  
  494. /* Return truth value of wheterh OP is EQ or NE.  */
  495. int
  496. eq_or_neq (op, mode)
  497.      rtx op;
  498.      enum machine_mode mode;
  499. {
  500.   return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
  501. }
  502.  
  503. /* Return truth value of whether OP can be used as an operands in a three
  504.    address arithmetic insn (such as add %o1,7,%l2) of mode MODE.  */
  505.  
  506. int
  507. arith_operand (op, mode)
  508.      rtx op;
  509.      enum machine_mode mode;
  510. {
  511.   return (register_operand (op, mode)
  512.       || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
  513. }
  514.  
  515. /* Return truth value of whether OP can be used as an operand in a two
  516.    address arithmetic insn (such as set 123456,%o4) of mode MODE.  */
  517.  
  518. int
  519. arith32_operand (op, mode)
  520.      rtx op;
  521.      enum machine_mode mode;
  522. {
  523.   return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
  524. }
  525.  
  526. /* Return truth value of whether OP is a integer which fits the
  527.    range constraining immediate operands in three-address insns.  */
  528.  
  529. int
  530. small_int (op, mode)
  531.      rtx op;
  532.      enum machine_mode mode;
  533. {
  534.   return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
  535. }
  536.  
  537. /* Return the best assembler insn template
  538.    for moving operands[1] into operands[0] as a fullword.  */
  539.  
  540. static char *
  541. singlemove_string (operands)
  542.      rtx *operands;
  543. {
  544.   if (GET_CODE (operands[0]) == MEM)
  545.     {
  546.       if (GET_CODE (operands[1]) != MEM)
  547.     if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
  548.       {
  549.         if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  550.            && cc_prev_status.mdep == XEXP (operands[0], 0)))
  551.           output_asm_insn ("sethi %%hi(%m0),%%g1", operands);
  552.         cc_status.flags |= CC_KNOW_HI_G1;
  553.         cc_status.mdep = XEXP (operands[0], 0);
  554.         return "st %1,[%%lo(%m0)+%%g1]";
  555.       }
  556.     else
  557.       return "st %r1,%0";
  558.       else
  559.     {
  560.       rtx xoperands[2];
  561.  
  562.       cc_status.flags &= ~CC_F0_IS_0;
  563.       xoperands[0] = gen_rtx (REG, SFmode, 32);
  564.       xoperands[1] = operands[1];
  565.       output_asm_insn (singlemove_string (xoperands), xoperands);
  566.       xoperands[1] = xoperands[0];
  567.       xoperands[0] = operands[0];
  568.       output_asm_insn (singlemove_string (xoperands), xoperands);
  569.       return "";
  570.     }
  571.     }
  572.   if (GET_CODE (operands[1]) == MEM)
  573.     {
  574.       if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
  575.     {
  576.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  577.          && cc_prev_status.mdep == XEXP (operands[1], 0)))
  578.         output_asm_insn ("sethi %%hi(%m1),%%g1", operands);
  579.       cc_status.flags |= CC_KNOW_HI_G1;
  580.       cc_status.mdep = XEXP (operands[1], 0);
  581.       return "ld [%%lo(%m1)+%%g1],%0";
  582.     }
  583.       return "ld %1,%0";
  584.     }
  585.   return "mov %1,%0";
  586. }
  587.  
  588. /* Output assembler code to perform a doubleword move insn
  589.    with operands OPERANDS.  */
  590.  
  591. char *
  592. output_move_double (operands)
  593.      rtx *operands;
  594. {
  595.   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
  596.   rtx latehalf[2];
  597.   rtx addreg0 = 0, addreg1 = 0;
  598.  
  599.   /* First classify both operands.  */
  600.  
  601.   if (REG_P (operands[0]))
  602.     optype0 = REGOP;
  603.   else if (offsettable_memref_p (operands[0]))
  604.     optype0 = OFFSOP;
  605.   else if (GET_CODE (operands[0]) == MEM)
  606.     optype0 = MEMOP;
  607.   else
  608.     optype0 = RNDOP;
  609.  
  610.   if (REG_P (operands[1]))
  611.     optype1 = REGOP;
  612.   else if (CONSTANT_P (operands[1])
  613.        || GET_CODE (operands[1]) == CONST_DOUBLE)
  614.     optype1 = CNSTOP;
  615.   else if (offsettable_memref_p (operands[1]))
  616.     optype1 = OFFSOP;
  617.   else if (GET_CODE (operands[1]) == MEM)
  618.     optype1 = MEMOP;
  619.   else
  620.     optype1 = RNDOP;
  621.  
  622.   /* Check for the cases that the operand constraints are not
  623.      supposed to allow to happen.  Abort if we get one,
  624.      because generating code for these cases is painful.  */
  625.  
  626.   if (optype0 == RNDOP || optype1 == RNDOP)
  627.     abort ();
  628.  
  629.   /* If an operand is an unoffsettable memory ref, find a register
  630.      we can increment temporarily to make it refer to the second word.  */
  631.  
  632.   if (optype0 == MEMOP)
  633.     addreg0 = find_addr_reg (XEXP (operands[0], 0));
  634.  
  635.   if (optype1 == MEMOP)
  636.     addreg1 = find_addr_reg (XEXP (operands[1], 0));
  637.  
  638.   /* Ok, we can do one word at a time.
  639.      Normally we do the low-numbered word first,
  640.      but if either operand is autodecrementing then we
  641.      do the high-numbered word first.
  642.  
  643.      In either case, set up in LATEHALF the operands to use
  644.      for the high-numbered word and in some cases alter the
  645.      operands in OPERANDS to be suitable for the low-numbered word.  */
  646.  
  647.   if (optype0 == REGOP)
  648.     latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
  649.   else if (optype0 == OFFSOP)
  650.     latehalf[0] = adj_offsettable_operand (operands[0], 4);
  651.   else
  652.     latehalf[0] = operands[0];
  653.  
  654.   if (optype1 == REGOP)
  655.     latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
  656.   else if (optype1 == OFFSOP)
  657.     latehalf[1] = adj_offsettable_operand (operands[1], 4);
  658.   else if (optype1 == CNSTOP)
  659.     {
  660.       if (CONSTANT_P (operands[1]))
  661.     latehalf[1] = const0_rtx;
  662.       else if (GET_CODE (operands[1]) == CONST_DOUBLE)
  663.     {
  664.       latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
  665.                  CONST_DOUBLE_HIGH (operands[1]));
  666.       operands[1] = gen_rtx (CONST_INT, VOIDmode,
  667.                  CONST_DOUBLE_LOW (operands[1]));
  668.     }
  669.     }
  670.   else
  671.     latehalf[1] = operands[1];
  672.  
  673.   /* If the first move would clobber the source of the second one,
  674.      do them in the other order.
  675.  
  676.      RMS says "This happens only for registers;
  677.      such overlap can't happen in memory unless the user explicitly
  678.      sets it up, and that is an undefined circumstance."
  679.  
  680.      but it happens on the sparc when loading parameter registers,
  681.      so I am going to define that circumstance, and make it work
  682.      as expected.  */
  683.  
  684.   /* Easy case: try moving both words at once.  */
  685.   /* First check for moving between an even/odd register pair
  686.      and a memory location.  */
  687.   if ((optype0 == REGOP && optype1 != REGOP && optype1 != CNSTOP
  688.        && (REGNO (operands[0]) & 1) == 0)
  689.       || (optype0 != REGOP && optype1 != CNSTOP && optype1 == REGOP
  690.       && (REGNO (operands[1]) & 1) == 0))
  691.     {
  692.       rtx op1, op2;
  693.       rtx base = 0, offset = const0_rtx;
  694.  
  695.       /* OP1 gets the register pair, and OP2 gets the memory address.  */
  696.       if (optype0 == REGOP)
  697.     op1 = operands[0], op2 = XEXP (operands[1], 0);
  698.       else
  699.     op1 = operands[1], op2 = XEXP (operands[0], 0);
  700.  
  701.       /* Now see if we can trust the address to be 8-byte aligned.  */
  702.       /* Trust global variables.  */
  703.       if (CONSTANT_ADDRESS_P (op2))
  704.     {
  705.       operands[0] = op1;
  706.       operands[1] = op2;
  707.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  708.          && cc_prev_status.mdep == op2))
  709.         output_asm_insn ("sethi %%hi(%1),%%g1", operands);
  710.       cc_status.flags |= CC_KNOW_HI_G1;
  711.       cc_status.mdep = op2;
  712.       if (op1 == operands[0])
  713.         return "ldd [%%lo(%1)+%%g1],%0";
  714.       else
  715.         return "std [%%lo(%1)+%%g1],%0";
  716.     }
  717.  
  718.       if (GET_CODE (op2) == PLUS)
  719.     {
  720.       if (GET_CODE (XEXP (op2, 0)) == REG)
  721.         base = XEXP (op2, 0), offset = XEXP (op2, 1);
  722.       else if (GET_CODE (XEXP (op2, 1)) == REG)
  723.         base = XEXP (op2, 1), offset = XEXP (op2, 0);
  724.     }
  725.  
  726.       /* Trust round enough offsets from the stack or frame pointer.  */
  727.       if (base
  728.       && (REGNO (base) == FRAME_POINTER_REGNUM
  729.           || REGNO (base) == STACK_POINTER_REGNUM))
  730.     {
  731.       if (GET_CODE (offset) == CONST_INT
  732.           && (INTVAL (offset) & 0x7) == 0)
  733.         {
  734.           if (op1 == operands[0])
  735.         return "ldd %1,%0";
  736.           else
  737.         return "std %1,%0";
  738.         }
  739.     }
  740.       else
  741.     {
  742.       /* We know structs not on the stack are properly aligned.
  743.          Since a double asks for 8-byte alignment,
  744.          we know it must have got that if it is in a struct.
  745.          But a DImode need not be 8-byte aligned, because it could be a
  746.          struct containing two ints or pointers.  */
  747.  
  748.       /* Sun fucks us here.  We cannot trust references
  749.          to doubles via varying addresses.  It might be on the stack
  750.          even if we don't know that it is; and then it might not be
  751.          double-word aligned.  */
  752. #if 0
  753.       if (GET_CODE (operands[1]) == MEM && GET_MODE (operands[1]) == DFmode
  754.           && MEM_IN_STRUCT_P (operands[1]))
  755.         return "ldd %1,%0";
  756.       else if (GET_CODE (operands[0]) == MEM
  757.            && GET_MODE (operands[0]) == DFmode
  758.            && MEM_IN_STRUCT_P (operands[0]))
  759.         return "std %1,%0";
  760. #endif
  761.     }
  762.     }
  763.  
  764.   if (optype0 == REGOP && optype1 == REGOP
  765.       && REGNO (operands[0]) == REGNO (latehalf[1]))
  766.     {
  767.       /* Make any unoffsettable addresses point at high-numbered word.  */
  768.       if (addreg0)
  769.     output_asm_insn ("add %0,0x4,%0", &addreg0);
  770.       if (addreg1)
  771.     output_asm_insn ("add %0,0x4,%0", &addreg1);
  772.  
  773.       /* Do that word.  */
  774.       output_asm_insn (singlemove_string (latehalf), latehalf);
  775.  
  776.       /* Undo the adds we just did.  */
  777.       if (addreg0)
  778.     output_asm_insn ("add %0,-0x4,%0", &addreg0);
  779.       if (addreg1)
  780.     output_asm_insn ("add %0,-0x4,%0", &addreg0);
  781.  
  782.       /* Do low-numbered word.  */
  783.       return singlemove_string (operands);
  784.     }
  785.   else if (optype0 == REGOP && optype1 != REGOP
  786.        && reg_overlap_mentioned_p (operands[0], operands[1]))
  787.     {
  788.       /* Do the late half first.  */
  789.       output_asm_insn (singlemove_string (latehalf), latehalf);
  790.       /* Then clobber.  */
  791.       return singlemove_string (operands);
  792.     }
  793.  
  794.   /* Normal case: do the two words, low-numbered first.  */
  795.  
  796.   output_asm_insn (singlemove_string (operands), operands);
  797.  
  798.   /* Make any unoffsettable addresses point at high-numbered word.  */
  799.   if (addreg0)
  800.     output_asm_insn ("add %0,0x4,%0", &addreg0);
  801.   if (addreg1)
  802.     output_asm_insn ("add %0,0x4,%0", &addreg1);
  803.  
  804.   /* Do that word.  */
  805.   output_asm_insn (singlemove_string (latehalf), latehalf);
  806.  
  807.   /* Undo the adds we just did.  */
  808.   if (addreg0)
  809.     output_asm_insn ("add %0,-0x4,%0", &addreg0);
  810.   if (addreg1)
  811.     output_asm_insn ("add %0,-0x4,%0", &addreg1);
  812.  
  813.   return "";
  814. }
  815.  
  816. static char *
  817. output_fp_move_double (operands)
  818.      rtx *operands;
  819. {
  820.   if (FP_REG_P (operands[0]))
  821.     {
  822.       if (FP_REG_P (operands[1]))
  823.     {
  824.       output_asm_insn ("fmovs %1,%0", operands);
  825.       operands[0] = gen_rtx (REG, VOIDmode, REGNO (operands[0]) + 1);
  826.       operands[1] = gen_rtx (REG, VOIDmode, REGNO (operands[1]) + 1);
  827.       return "fmovs %1,%0";
  828.     }
  829.       if (GET_CODE (operands[1]) == REG)
  830.     {
  831.       if ((REGNO (operands[1]) & 1) == 0)
  832.         return "std %1,[%%fp-8]\n\tldd [%%fp-8],%0";
  833.       else
  834.         {
  835.           rtx xoperands[3];
  836.           xoperands[0] = operands[0];
  837.           xoperands[1] = operands[1];
  838.           xoperands[2] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
  839.           output_asm_insn ("st %2,[%%fp-4]\n\tst %1,[%%fp-8]\n\tldd [%%fp-8],%0", xoperands);
  840.           return "";
  841.         }
  842.     }
  843.       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
  844.       && (((XEXP (XEXP (operands[1], 0), 0) == frame_pointer_rtx
  845.           || XEXP (XEXP (operands[1], 0), 0) == stack_pointer_rtx)
  846.       && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT
  847.       && (INTVAL (XEXP (XEXP (operands[1], 0), 1)) & 0x7) == 0)
  848.           || (REG_P (XEXP (XEXP (operands[1], 0), 0))
  849.           && REG_P (XEXP (XEXP (operands[1], 0), 1)))))
  850.         {
  851.           return "ldd %1,%0";
  852.         }
  853.       if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
  854.     {
  855.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  856.          && cc_prev_status.mdep == XEXP (operands[1], 0)))
  857.         output_asm_insn ("sethi %%hi(%m1),%%g1", operands);
  858.       cc_status.flags |= CC_KNOW_HI_G1;
  859.       cc_status.mdep = XEXP (operands[1], 0);
  860.       return "ldd [%%lo(%m1)+%%g1],%0";
  861.     }
  862.     {
  863.       rtx xoperands[2];
  864.       output_asm_insn ("ld %1,%0", operands);
  865.       xoperands[0] = gen_rtx (REG, GET_MODE (operands[0]),
  866.                   REGNO (operands[0]) + 1);
  867.       xoperands[1] = gen_rtx (MEM, GET_MODE (operands[1]),
  868.                   plus_constant (XEXP (operands[1], 0), 4));
  869.       output_asm_insn ("ld %1,%0", xoperands);
  870.       return "";
  871.     }
  872.     }
  873.   else if (FP_REG_P (operands[1]))
  874.     {
  875.       if (GET_CODE (operands[0]) == REG)
  876.     {
  877.       if ((REGNO (operands[0]) & 1) == 0)
  878.         return "std %1,[%%fp-8]\n\tldd [%%fp-8],%0";
  879.       else
  880.         {
  881.           rtx xoperands[3];
  882.           xoperands[2] = operands[1];
  883.           xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
  884.           xoperands[0] = operands[0];
  885.           output_asm_insn ("std %2,[%%fp-8]\n\tld [%%fp-4],%1\n\tld [%%fp-8],%0", xoperands);
  886.           return "";
  887.         }
  888.     }
  889.       /* Use std if we can be sure it is well-aligned.  */
  890.       if (GET_CODE (XEXP (operands[0], 0)) == PLUS
  891.       && (((XEXP (XEXP (operands[0], 0), 0) == frame_pointer_rtx
  892.         || XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx)
  893.            && GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == CONST_INT
  894.            && (INTVAL (XEXP (XEXP (operands[0], 0), 1)) & 0x7) == 0)
  895.           /* Arrays are known to be aligned,
  896.          and reg+reg addresses are used (on this machine)
  897.          only for array accesses.  */
  898.           || (REG_P (XEXP (XEXP (operands[0], 0), 0))
  899.           && REG_P (XEXP (XEXP (operands[0], 0), 1)))))
  900.     return "std %1,%0";
  901.       if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
  902.     {
  903.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  904.          && cc_prev_status.mdep == XEXP (operands[0], 0)))
  905.         output_asm_insn ("sethi %%hi(%m0),%%g1", operands);
  906.       cc_status.flags |= CC_KNOW_HI_G1;
  907.       cc_status.mdep = XEXP (operands[0], 0);
  908.       return "std %1,[%%lo(%m0)+%%g1]";
  909.     }
  910.       /* Otherwise use two st insns.  */
  911.       {
  912.     rtx xoperands[2];
  913.     output_asm_insn ("st %r1,%0", operands);
  914.     xoperands[1] = gen_rtx (REG, GET_MODE (operands[1]),
  915.                 REGNO (operands[1]) + 1);
  916.     xoperands[0] = gen_rtx (MEM, GET_MODE (operands[0]),
  917.                 plus_constant (XEXP (operands[0], 0), 4));
  918.     output_asm_insn ("st %r1,%0", xoperands);
  919.     return "";
  920.       }
  921.     }
  922.   else abort ();
  923. }
  924.  
  925. /* Return a REG that occurs in ADDR with coefficient 1.
  926.    ADDR can be effectively incremented by incrementing REG.  */
  927.  
  928. static rtx
  929. find_addr_reg (addr)
  930.      rtx addr;
  931. {
  932.   while (GET_CODE (addr) == PLUS)
  933.     {
  934.       if (GET_CODE (XEXP (addr, 0)) == REG)
  935.     addr = XEXP (addr, 0);
  936.       else if (GET_CODE (XEXP (addr, 1)) == REG)
  937.     addr = XEXP (addr, 1);
  938.       else if (CONSTANT_P (XEXP (addr, 0)))
  939.     addr = XEXP (addr, 1);
  940.       else if (CONSTANT_P (XEXP (addr, 1)))
  941.     addr = XEXP (addr, 0);
  942.       else
  943.     abort ();
  944.     }
  945.   if (GET_CODE (addr) == REG)
  946.     return addr;
  947.   abort ();
  948. }
  949.  
  950. void
  951. output_sized_memop (opname, mode)
  952.      char *opname;
  953.      enum machine_mode mode;
  954. {
  955.   extern struct _iobuf *asm_out_file;
  956.  
  957.   static char *ld_size_suffix[] = { "ub", "uh", "", "?", "d" };
  958.   static char *st_size_suffix[] = { "b", "h", "", "?", "d" };
  959.   char *modename
  960.     = (opname[0] == 'l' ? ld_size_suffix : st_size_suffix)[GET_MODE_SIZE (mode) >> 1];
  961.  
  962.   fprintf (asm_out_file, "\t%s%s", opname, modename);
  963. }
  964.  
  965. /* Output a store-in-memory whose operands are OPERANDS[0,1].
  966.    OPERANDS[0] is a MEM, and OPERANDS[1] is a reg or zero.  */
  967.  
  968. char *
  969. output_store (operands)
  970.      rtx *operands;
  971. {
  972.   enum machine_mode mode = GET_MODE (operands[0]);
  973.   rtx address = XEXP (operands[0], 0);
  974.  
  975.   cc_status.flags |= CC_KNOW_HI_G1;
  976.   cc_status.mdep = address;
  977.  
  978.   if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  979.      && address == cc_prev_status.mdep))
  980.     {
  981.       output_asm_insn ("sethi %%hi(%m0),%%g1", operands);
  982.       cc_prev_status.mdep = address;
  983.     }
  984.  
  985.   /* Store zero in two parts when appropriate.  */
  986.   if (mode == DFmode && operands[1] == dconst0_rtx)
  987.     {
  988.       /* We can't cross a page boundary here because the
  989.      SYMBOL_REF must be double word aligned, and for this
  990.      to be the case, SYMBOL_REF+4 cannot cross.  */
  991.       output_sized_memop ("st", SImode);
  992.       output_asm_insn ("%r1,[%%g1+%%lo(%m0)]", operands);
  993.       output_sized_memop ("st", SImode);
  994.       return "%r1,[%%g1+%%lo(%m0)+4]";
  995.     }
  996.  
  997.   /* Code below isn't smart enough to move a doubleword in two parts,
  998.      so use output_move_double to do that in the cases that require it.  */
  999.   if ((mode == DImode || mode == DFmode)
  1000.       && (GET_CODE (operands[1]) == REG
  1001.       && (REGNO (operands[1]) & 1)))
  1002.     return output_move_double (operands);
  1003.  
  1004.   output_sized_memop ("st", mode);
  1005.   return "%r1,[%%g1+%%lo(%m0)]";
  1006. }
  1007.  
  1008. /* Output a fixed-point load-from-memory whose operands are OPERANDS[0,1].
  1009.    OPERANDS[0] is a reg, and OPERANDS[1] is a mem.  */
  1010.  
  1011. char *
  1012. output_load_fixed (operands)
  1013.      rtx *operands;
  1014. {
  1015.   enum machine_mode mode = GET_MODE (operands[0]);
  1016.   rtx address = XEXP (operands[1], 0);
  1017.  
  1018.   /* We don't bother trying to see if we know %hi(address).
  1019.      This is because we are doing a load, and if we know the
  1020.      %hi value, we probably also know that value in memory.  */
  1021.   cc_status.flags |= CC_KNOW_HI_G1;
  1022.   cc_status.mdep = address;
  1023.  
  1024.   if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  1025.      && address == cc_prev_status.mdep
  1026.      && cc_prev_status.mdep == cc_status.mdep))
  1027.     {
  1028.       output_asm_insn ("sethi %%hi(%m1),%%g1", operands);
  1029.       cc_prev_status.mdep = address;
  1030.     }
  1031.  
  1032.   /* Code below isn't smart enough to do a doubleword in two parts.
  1033.      So handle that case the slow way.  */
  1034.   if (mode == DImode
  1035.       && GET_CODE (operands[0]) == REG   /* Moving to nonaligned reg pair */
  1036.       && (REGNO (operands[0]) & 1))
  1037.     return output_move_double (operands);
  1038.  
  1039.   output_sized_memop ("ld", mode);
  1040.   if (GET_CODE (operands[0]) == REG)
  1041.     return "[%%g1+%%lo(%m1)],%0";
  1042.   abort ();
  1043. }
  1044.  
  1045. /* Output a floating-point load-from-memory whose operands are OPERANDS[0,1].
  1046.    OPERANDS[0] is a reg, and OPERANDS[1] is a mem.
  1047.    We also handle the case where OPERANDS[0] is a mem.  */
  1048.  
  1049. char *
  1050. output_load_floating (operands)
  1051.      rtx *operands;
  1052. {
  1053.   enum machine_mode mode = GET_MODE (operands[0]);
  1054.   rtx address = XEXP (operands[1], 0);
  1055.  
  1056.   /* We don't bother trying to see if we know %hi(address).
  1057.      This is because we are doing a load, and if we know the
  1058.      %hi value, we probably also know that value in memory.  */
  1059.   cc_status.flags |= CC_KNOW_HI_G1;
  1060.   cc_status.mdep = address;
  1061.  
  1062.   if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  1063.      && address == cc_prev_status.mdep
  1064.      && cc_prev_status.mdep == cc_status.mdep))
  1065.     {
  1066.       output_asm_insn ("sethi %%hi(%m1),%%g1", operands);
  1067.       cc_prev_status.mdep = address;
  1068.     }
  1069.  
  1070.   if (mode == DFmode)
  1071.     {
  1072.       if (REG_P (operands[0]))
  1073.     {
  1074.       if (REGNO (operands[0]) & 1)
  1075.         return output_move_double (operands);
  1076.       else
  1077.         return "ldd [%%g1+%%lo(%m1)],%0";
  1078.     }
  1079.       cc_status.flags &= ~(CC_F0_IS_0|CC_F1_IS_0);
  1080.       output_asm_insn ("ldd [%%g1+%%lo(%m1)],%%f0", operands);
  1081.       operands[1] = gen_rtx (REG, DFmode, 32);
  1082.       return output_fp_move_double (operands);
  1083.     }
  1084.  
  1085.   if (GET_CODE (operands[0]) == MEM)
  1086.     {
  1087.       cc_status.flags &= ~CC_F1_IS_0;
  1088.       output_asm_insn ("ld [%%g1+%%lo(%1)],%%f1", operands);
  1089.       if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
  1090.     {
  1091.       cc_status.mdep = XEXP (operands[0], 0);
  1092.       return "sethi %%hi(%m0),%%g1\n\tst %%f1,[%%g1+%%lo(%m0)]";
  1093.     }
  1094.       else
  1095.     return "st %%f1,%0";
  1096.     }
  1097.   return "ld [%%g1+%%lo(%m1)],%0";
  1098. }
  1099.  
  1100. /* Load the address specified by OPERANDS[3] into the register
  1101.    specified by OPERANDS[0].
  1102.  
  1103.    OPERANDS[3] may be the result of a sum, hence it could either be:
  1104.  
  1105.    (1) CONST
  1106.    (2) REG
  1107.    (2) REG + CONST_INT
  1108.    (3) REG + REG + CONST_INT
  1109.    (4) REG + REG  (special case of 3).
  1110.  
  1111.    Note that (3) is not a legitimate address.
  1112.    All cases are handled here.  */
  1113.  
  1114. void
  1115. output_load_address (operands)
  1116.      rtx *operands;
  1117. {
  1118.   rtx base, offset;
  1119.  
  1120.   if (CONSTANT_P (operands[3]))
  1121.     {
  1122.       output_asm_insn ("set %3,%0", operands);
  1123.       return;
  1124.     }
  1125.  
  1126.   if (REG_P (operands[3]))
  1127.     {
  1128.       if (REGNO (operands[0]) != REGNO (operands[3]))
  1129.     output_asm_insn ("mov %3,%0", operands);
  1130.       return;
  1131.     }
  1132.  
  1133.   if (GET_CODE (operands[3]) != PLUS)
  1134.     abort ();
  1135.  
  1136.   base = XEXP (operands[3], 0);
  1137.   offset = XEXP (operands[3], 1);
  1138.  
  1139.   if (GET_CODE (base) == CONST_INT)
  1140.     {
  1141.       rtx tmp = base;
  1142.       base = offset;
  1143.       offset = tmp;
  1144.     }
  1145.  
  1146.   if (GET_CODE (offset) != CONST_INT)
  1147.     {
  1148.       /* Operand is (PLUS (REG) (REG)).  */
  1149.       base = operands[3];
  1150.       offset = const0_rtx;
  1151.     }
  1152.  
  1153.   if (REG_P (base))
  1154.     {
  1155.       operands[6] = base;
  1156.       operands[7] = offset;
  1157.       if (SMALL_INT (offset))
  1158.     output_asm_insn ("add %6,%7,%0", operands);
  1159.       else
  1160.     output_asm_insn ("set %7,%0\n\tadd %0,%6,%0", operands);
  1161.     }
  1162.   else if (GET_CODE (base) == PLUS)
  1163.     {
  1164.       operands[6] = XEXP (base, 0);
  1165.       operands[7] = XEXP (base, 1);
  1166.       operands[8] = offset;
  1167.  
  1168.       if (SMALL_INT (offset))
  1169.     output_asm_insn ("add %6,%7,%0\n\tadd %0,%8,%0", operands);
  1170.       else
  1171.     output_asm_insn ("set %8,%0\n\tadd %0,%6,%0\n\tadd %0,%7,%0", operands);
  1172.     }
  1173.   else
  1174.     abort ();
  1175. }
  1176.  
  1177. /* Output code to place a size count SIZE in register REG.
  1178.    ALIGN is the size of the unit of transfer.
  1179.  
  1180.    Because block moves are pipelined, we don't include the
  1181.    first element in the transfer of SIZE to REG.  */
  1182.  
  1183. static void
  1184. output_size_for_block_move (size, reg, align)
  1185.      rtx size, reg;
  1186.      rtx align;
  1187. {
  1188.   rtx xoperands[3];
  1189.  
  1190.   xoperands[0] = reg;
  1191.   xoperands[1] = size;
  1192.   xoperands[2] = align;
  1193.   if (GET_CODE (size) == REG)
  1194.     output_asm_insn ("sub %1,%2,%0", xoperands);
  1195.   else
  1196.     {
  1197.       xoperands[1]
  1198.     = gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - INTVAL (align));
  1199.       cc_status.flags &= ~ CC_KNOW_HI_G1;
  1200.       output_asm_insn ("set %1,%0", xoperands);
  1201.     }
  1202. }
  1203.  
  1204. /* Emit code to perform a block move.
  1205.  
  1206.    OPERANDS[0] is the destination.
  1207.    OPERANDS[1] is the source.
  1208.    OPERANDS[2] is the size.
  1209.    OPERANDS[3] is the alignment safe to use.
  1210.    OPERANDS[4] is a register we can safely clobber as a temp.  */
  1211.  
  1212. char *
  1213. output_block_move (operands)
  1214.      rtx *operands;
  1215. {
  1216.   /* A vector for our computed operands.  Note that load_output_address
  1217.      makes use of (and can clobber) up to the 8th element of this vector.  */
  1218.   rtx xoperands[10];
  1219.   rtx zoperands[10];
  1220.   static int movstrsi_label = 0;
  1221.   int i, j;
  1222.   rtx temp1 = operands[4];
  1223.   rtx alignrtx = operands[3];
  1224.   int align = INTVAL (alignrtx);
  1225.  
  1226.   xoperands[0] = operands[0];
  1227.   xoperands[1] = operands[1];
  1228.   xoperands[2] = temp1;
  1229.  
  1230.   /* We can't move more than four bytes at a time
  1231.      because we have only one register to move them through.  */
  1232.   if (align > 4)
  1233.     {
  1234.       align = 4;
  1235.       alignrtx = gen_rtx (CONST_INT, VOIDmode, 4);
  1236.     }
  1237.  
  1238.   /* Since we clobber untold things, nix the condition codes.  */
  1239.   CC_STATUS_INIT;
  1240.  
  1241.   /* Recognize special cases of block moves.  These occur
  1242.      when GNU C++ is forced to treat something as BLKmode
  1243.      to keep it in memory, when its mode could be represented
  1244.      with something smaller.
  1245.  
  1246.      We cannot do this for global variables, since we don't know
  1247.      what pages they don't cross.  Sigh.  */
  1248.   if (GET_CODE (operands[2]) == CONST_INT
  1249.       && INTVAL (operands[2]) <= 16
  1250.       && ! CONSTANT_ADDRESS_P (operands[0])
  1251.       && ! CONSTANT_ADDRESS_P (operands[1]))
  1252.     {
  1253.       int size = INTVAL (operands[2]);
  1254.  
  1255.       cc_status.flags &= ~CC_KNOW_HI_G1;
  1256.       if (align == 1)
  1257.     {
  1258.       if (memory_address_p (QImode, plus_constant (xoperands[0], size))
  1259.           && memory_address_p (QImode, plus_constant (xoperands[1], size)))
  1260.         {
  1261.           /* We will store different integers into this particular RTX.  */
  1262.           xoperands[2] = gen_rtx (CONST_INT, VOIDmode, 13);
  1263.           for (i = size-1; i >= 0; i--)
  1264.         {
  1265.           INTVAL (xoperands[2]) = i;
  1266.           output_asm_insn ("ldub [%a1+%2],%%g1\n\tstb %%g1,[%a0+%2]",
  1267.                    xoperands);
  1268.         }
  1269.           return "";
  1270.         }
  1271.     }
  1272.       else if (align == 2)
  1273.     {
  1274.       if (memory_address_p (HImode, plus_constant (xoperands[0], size))
  1275.           && memory_address_p (HImode, plus_constant (xoperands[1], size)))
  1276.         {
  1277.           /* We will store different integers into this particular RTX.  */
  1278.           xoperands[2] = gen_rtx (CONST_INT, VOIDmode, 13);
  1279.           for (i = (size>>1)-1; i >= 0; i--)
  1280.         {
  1281.           INTVAL (xoperands[2]) = i<<1;
  1282.           output_asm_insn ("lduh [%a1+%2],%%g1\n\tsth %%g1,[%a0+%2]",
  1283.                    xoperands);
  1284.         }
  1285.           return "";
  1286.         }
  1287.     }
  1288.       else
  1289.     {
  1290.       if (memory_address_p (SImode, plus_constant (xoperands[0], size))
  1291.           && memory_address_p (SImode, plus_constant (xoperands[1], size)))
  1292.         {
  1293.           /* We will store different integers into this particular RTX.  */
  1294.           xoperands[2] = gen_rtx (CONST_INT, VOIDmode, 13);
  1295.           for (i = (size>>2)-1; i >= 0; i--)
  1296.         {
  1297.           INTVAL (xoperands[2]) = i<<2;
  1298.           output_asm_insn ("ld [%a1+%2],%%g1\n\tst %%g1,[%a0+%2]",
  1299.                    xoperands);
  1300.         }
  1301.           return "";
  1302.         }
  1303.     }
  1304.     }
  1305.  
  1306.   /* This is the size of the transfer.
  1307.      Either use the register which already contains the size,
  1308.      or use a free register (used by no operands).
  1309.      Also emit code to decrement the size value by ALIGN.  */
  1310.   output_size_for_block_move (operands[2], temp1, alignrtx);
  1311.      
  1312.   zoperands[0] = operands[0];
  1313.   zoperands[3] = plus_constant (operands[0], align);
  1314.   output_load_address (zoperands);
  1315.  
  1316.   xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
  1317.   xoperands[4] = gen_rtx (CONST_INT, VOIDmode, align);
  1318.  
  1319.   if (align == 1)
  1320.     output_asm_insn ("\nLm%3:\n\tldub [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tstb %%g1,[%0+%2]", xoperands);
  1321.   else if (align == 2)
  1322.     output_asm_insn ("\nLm%3:\n\tlduh [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tsth %%g1,[%0+%2]", xoperands);
  1323.   else
  1324.     output_asm_insn ("\nLm%3:\n\tld [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tst %%g1,[%0+%2]", xoperands);
  1325.   return "";
  1326. }
  1327.  
  1328. /* What the sparc lacks in hardware, make up for in software.
  1329.    Compute a fairly good sequence of shift and add insns
  1330.    to make a multiply happen.  */
  1331.  
  1332. #define ABS(x) ((x) < 0 ? -(x) : x)
  1333.  
  1334. char *
  1335. output_mul_by_constant (insn, operands, unsignedp)
  1336.      rtx insn;
  1337.      rtx *operands;
  1338.      int unsignedp;
  1339. {
  1340.   int c;            /* Size of constant */
  1341.   int shifts[BITS_PER_WORD];    /* Table of shifts */
  1342.   unsigned int p, log;        /* A power of two, and its log */
  1343.   int d1, d2;            /* Differences of c and p */
  1344.   int first = 1;        /* True if dst has unknown data in it */
  1345.   int i;
  1346.  
  1347.   CC_STATUS_INIT;
  1348.  
  1349.   c = INTVAL (operands[2]);
  1350.   if (c == 0)
  1351.     {
  1352.       /* should not happen.  */
  1353.       abort ();
  1354.       if (GET_CODE (operands[0]) == MEM)
  1355.     return "st %%g0,%0";
  1356.       return "mov %%g0,%0";
  1357.     }
  1358.  
  1359.   output_asm_insn ("! start open coded multiply");
  1360.  
  1361.   /* Clear out the table of shifts. */
  1362.   for (i = 0; i < BITS_PER_WORD; ++i)
  1363.     shifts[i] = 0;
  1364.  
  1365.   while (c)
  1366.     {
  1367.       /* Find the power of two nearest ABS(c) */
  1368.       p = 1, log = 0;
  1369.       do
  1370.     {
  1371.       d1 = ABS(c) - p;
  1372.       p *= 2;
  1373.       ++log;
  1374.     }
  1375.       while (p < ABS(c));
  1376.       d2 = p - ABS(c);
  1377.  
  1378.       /* Make an appropriate entry in shifts for p. */
  1379.       if (d2 < d1)
  1380.     {
  1381.       shifts[log] = c < 0 ? -1 : 1;
  1382.       c = c < 0 ? d2 : -d2;
  1383.     }
  1384.       else
  1385.     {
  1386.       shifts[log - 1] = c < 0 ? -1 : 1;
  1387.       c = c < 0 ? -d1 : d1;
  1388.     }
  1389.     }
  1390.  
  1391.   /* Take care of the first insn in sequence.
  1392.      We know we have at least one. */
  1393.  
  1394.   /* A value of -1 in shifts says to subtract that power of two, and a value
  1395.      of 1 says to add that power of two. */
  1396.   for (i = 0; ; i++)
  1397.     if (shifts[i])
  1398.       {
  1399.     if (i)
  1400.       {
  1401.         operands[2] = gen_rtx (CONST_INT, VOIDmode, i);
  1402.         output_asm_insn ("sll %1,%2,%%g1", operands);
  1403.       }
  1404.     else output_asm_insn ("mov %1,%%g1", operands);
  1405.  
  1406.     log = i;
  1407.     if (shifts[i] < 0)
  1408.       output_asm_insn ("sub %%g0,%%g1,%0", operands);
  1409.     else
  1410.       output_asm_insn ("mov %%g1,%0", operands);
  1411.     break;
  1412.       }
  1413.  
  1414.   /* A value of -1 in shifts says to subtract that power of two, and a value
  1415.      of 1 says to add that power of two--continued.  */
  1416.   for (i += 1; i < BITS_PER_WORD; ++i)
  1417.     if (shifts[i])
  1418.       {
  1419.     if (i - log > 0)
  1420.       {
  1421.         operands[2] = gen_rtx (CONST_INT, VOIDmode, i - log);
  1422.         output_asm_insn ("sll %%g1,%2,%%g1", operands);
  1423.       }
  1424.     else
  1425.       {
  1426.         operands[2] = gen_rtx (CONST_INT, VOIDmode, log - i);
  1427.         output_asm_insn ("sra %%g1,%2,%%g1", operands);
  1428.       }
  1429.     log = i;
  1430.     if (shifts[i] < 0)
  1431.       output_asm_insn ("sub %0,%%g1,%0", operands);
  1432.     else
  1433.       output_asm_insn ("add %0,%%g1,%0", operands);
  1434.       }
  1435.  
  1436.   output_asm_insn ("! end open coded multiply");
  1437.  
  1438.   return "";
  1439. }
  1440.  
  1441. char *
  1442. output_mul_insn (operands, unsignedp)
  1443.      rtx *operands;
  1444.      int unsignedp;
  1445. {
  1446.   int lucky1 = ((unsigned)REGNO (operands[1]) - 8) <= 1;
  1447.   int lucky2 = ((unsigned)REGNO (operands[2]) - 8) <= 1;
  1448.  
  1449.   CC_STATUS_INIT;
  1450.  
  1451.   if (lucky1)
  1452.     {
  1453.       if (lucky2)
  1454.     {
  1455.       if (REGNO (operands[1]) == REGNO (operands[2]))
  1456.         {
  1457.           if (REGNO (operands[1]) == 8)
  1458.         output_asm_insn ("mov %%o0,%%o1");
  1459.           else
  1460.         output_asm_insn ("mov %%o1,%%o0");
  1461.         }
  1462.       output_asm_insn ("call .mul,2\n\tnop", operands);
  1463.     }
  1464.       else
  1465.     {
  1466.       rtx xoperands[2];
  1467.       xoperands[0] = gen_rtx (REG, SImode,
  1468.                   8 ^ (REGNO (operands[1]) == 8));
  1469.       xoperands[1] = operands[2];
  1470.       output_asm_insn ("call .mul,2\n\tmov %1,%0", xoperands);
  1471.     }
  1472.     }
  1473.   else if (lucky2)
  1474.     {
  1475.       rtx xoperands[2];
  1476.       xoperands[0] = gen_rtx (REG, SImode,
  1477.                   8 ^ (REGNO (operands[2]) == 8));
  1478.       xoperands[1] = operands[1];
  1479.       output_asm_insn ("call .mul,2\n\tmov %1,%0", xoperands);
  1480.     }
  1481.   else
  1482.     {
  1483.       output_asm_insn ("mov %1,%%o0\n\tcall .mul,2\n\tmov %2,%%o1",
  1484.                operands);
  1485.     }
  1486.  
  1487.   if (REGNO (operands[0]) == 8)
  1488.     return "";
  1489.   return "mov %%o0,%0";
  1490. }
  1491.  
  1492. /* Make floating point register f0 contain 0.
  1493.    SIZE is the number of registers (including f0)
  1494.    which should contain 0.  */
  1495.  
  1496. void
  1497. make_f0_contain_0 (size)
  1498.      int size;
  1499. {
  1500.   if (size == 1)
  1501.     {
  1502.       if ((cc_status.flags & (CC_F0_IS_0)) == 0)
  1503.     output_asm_insn ("ld [%%fp-16],%%f0", 0);
  1504.       cc_status.flags |= CC_F0_IS_0;
  1505.     }
  1506.   else if (size == 2)
  1507.     {
  1508.       if ((cc_status.flags & CC_F0_IS_0) == 0)
  1509.     output_asm_insn ("ld [%%fp-16],%%f0", 0);
  1510.       if ((cc_status.flags & (CC_F1_IS_0)) == 0)
  1511.     output_asm_insn ("ld [%%fp-12],%%f1", 0);
  1512.       cc_status.flags |= CC_F0_IS_0 | CC_F1_IS_0;
  1513.     }
  1514. }
  1515.  
  1516. /* Since condition codes don't have logical links, we need to keep
  1517.    their setting and use together for set-cc insns.  */
  1518. void
  1519. gen_scc_insn (code, mode, operands)
  1520.      enum rtx_code code;
  1521.      enum machine_mode mode;
  1522.      rtx *operands;
  1523. {
  1524.   extern rtx sequence_stack;
  1525.   rtx last_insn = XEXP (XEXP (sequence_stack, 1), 0);
  1526.   rtx last_pat;
  1527.  
  1528.   /* Skip back over the CLOBBERs that may precede this insn.  */
  1529.   while (last_insn && GET_CODE (last_insn) == INSN
  1530.      && GET_CODE (PATTERN (last_insn)) == CLOBBER)
  1531.     last_insn = PREV_INSN (last_insn);
  1532.   /* We should have found the preceding compare.  */
  1533.   if (last_insn == 0 || GET_CODE (last_insn) != INSN)
  1534.     abort ();
  1535.   last_pat = PATTERN (last_insn);
  1536.   if (GET_CODE (last_pat) != SET
  1537.       || GET_CODE (SET_DEST (last_pat)) != CC0)
  1538.     abort ();
  1539.  
  1540.   /* Turn off that previous insn, now that we have got the data out of it.  */
  1541.   PUT_CODE (last_insn, NOTE);
  1542.   NOTE_LINE_NUMBER (last_insn) = NOTE_INSN_DELETED;
  1543.  
  1544.   /* Emit one replacement insn to compare operands and store result.  */
  1545.   emit_insn (gen_rtx (SET, VOIDmode, operands[0],
  1546.               gen_rtx (code, mode, SET_SRC (last_pat), const0_rtx)));
  1547. }
  1548.  
  1549. /* Output reasonable peephole for set-on-condition-code insns.
  1550.    Note that these insns assume a particular way of defining
  1551.    labels.  Therefore, *both* tm-sparc.h and this function must
  1552.    be changed if a new syntax is needed.  */
  1553.  
  1554. char *
  1555. output_scc_insn (code, operand)
  1556.      enum rtx_code code;
  1557.      rtx operand;
  1558. {
  1559.   rtx xoperands[2];
  1560.   rtx label = gen_label_rtx ();
  1561.   int cc_in_fccr = cc_status.flags & CC_IN_FCCR;
  1562.   int antisymmetric = 0;
  1563.  
  1564.   xoperands[0] = operand;
  1565.   xoperands[1] = label;
  1566.  
  1567.   switch (code)
  1568.     {
  1569.     case NE:
  1570.       if (cc_in_fccr)
  1571.     output_asm_insn ("fbne,a %l0", &label);
  1572.       else
  1573.     output_asm_insn ("bne,a %l0", &label);
  1574.       break;
  1575.     case EQ:
  1576.       if (cc_in_fccr)
  1577.     output_asm_insn ("fbe,a %l0", &label);
  1578.       else
  1579.     output_asm_insn ("be,a %l0", &label);
  1580.       break;
  1581.     case GE:
  1582.       if (cc_in_fccr)
  1583.     output_asm_insn ("fbge,a %l0", &label);
  1584.       else
  1585.     output_asm_insn ("bge,a %l0", &label);
  1586.       antisymmetric = 1;
  1587.       break;
  1588.     case GT:
  1589.       if (cc_in_fccr)
  1590.     output_asm_insn ("fbg,a %l0", &label);
  1591.       else
  1592.     output_asm_insn ("bg,a %l0", &label);
  1593.       antisymmetric = 1;
  1594.       break;
  1595.     case LE:
  1596.       if (cc_in_fccr)
  1597.     output_asm_insn ("fble,a %l0", &label);
  1598.       else
  1599.     output_asm_insn ("ble,a %l0", &label);
  1600.       antisymmetric = 1;
  1601.       break;
  1602.     case LT:
  1603.       if (cc_in_fccr)
  1604.     output_asm_insn ("fbl,a %l0", &label);
  1605.       else
  1606.     output_asm_insn ("bl,a %l0", &label);
  1607.       antisymmetric = 1;
  1608.       break;
  1609.     case GEU:
  1610.       if (cc_in_fccr)
  1611.     abort ();
  1612.       else
  1613.     output_asm_insn ("bgeu,a %l0", &label);
  1614.       antisymmetric = 1;
  1615.       break;
  1616.     case GTU:
  1617.       if (cc_in_fccr)
  1618.     abort ();
  1619.       else
  1620.     output_asm_insn ("bgu,a %l0", &label);
  1621.       antisymmetric = 1;
  1622.       break;
  1623.     case LEU:
  1624.       if (cc_in_fccr)
  1625.     abort ();
  1626.       else
  1627.     output_asm_insn ("bleu,a %l0", &label);
  1628.       antisymmetric = 1;
  1629.       break;
  1630.     case LTU:
  1631.       if (cc_in_fccr)
  1632.     abort ();
  1633.       else
  1634.     output_asm_insn ("blu,a %l0", &label);
  1635.       antisymmetric = 1;
  1636.       break;
  1637.     default:
  1638.       abort ();
  1639.     }
  1640.   if (antisymmetric
  1641.       && (cc_status.flags & CC_REVERSED))
  1642.     output_asm_insn ("orcc %%g0,0,%0\n\torcc %%g0,1,%0\n%l1:", xoperands);
  1643.   else
  1644.     output_asm_insn ("orcc %%g0,1,%0\n\torcc %%g0,0,%0\n%l1:", xoperands);
  1645.   return "";
  1646. }
  1647.  
  1648. /* Output a delayed branch insn with the delay insn in its
  1649.    branch slot.  The delayed branch insn template is in TEMPLATE,
  1650.    with operands OPERANDS.  The insn in its delay slot is INSN.
  1651.  
  1652.    As a special case, since we know that all memory transfers are via
  1653.    ld/st insns, if we see a (MEM (SYMBOL_REF ...)) we divide the memory
  1654.    reference around the branch as
  1655.  
  1656.     sethi %hi(x),%%g1
  1657.     b ...
  1658.     ld/st [%g1+%lo(x)],...
  1659.  
  1660.    As another special case, we handle loading (SYMBOL_REF ...) and
  1661.    other large constants around branches as well:
  1662.  
  1663.     sethi %hi(x),%0
  1664.     b ...
  1665.     or %0,%lo(x),%1
  1666.  
  1667.    */
  1668.  
  1669. char *
  1670. output_delayed_branch (template, operands, insn)
  1671.      char *template;
  1672.      rtx *operands;
  1673.      rtx insn;
  1674. {
  1675.   extern rtx recog_operand[];
  1676.   rtx src = XVECEXP (PATTERN (insn), 0, 1);
  1677.   rtx dest = XVECEXP (PATTERN (insn), 0, 0);
  1678.  
  1679.   if (GET_CODE (src) == SYMBOL_REF
  1680.       || (GET_CODE (src) == CONST_INT
  1681.       && !(SMALL_INT (src) || (INTVAL (src) & 0x3ff) == 0)))
  1682.     {
  1683.       rtx xoperands[2];
  1684.       xoperands[0] = dest;
  1685.       xoperands[1] = src;
  1686.  
  1687.       /* Output the `sethi' insn.  */
  1688.       output_asm_insn ("sethi %%hi(%1),%0", xoperands);
  1689.  
  1690.       /* Output the branch instruction next.  */
  1691.       output_asm_insn (template, operands);
  1692.  
  1693.       /* Now output the `or' insn.  */
  1694.       output_asm_insn ("or %0,%%lo(%1),%0", xoperands);
  1695.     }
  1696.   else if ((GET_CODE (src) == MEM
  1697.         && CONSTANT_ADDRESS_P (XEXP (src, 0)))
  1698.        || (GET_CODE (dest) == MEM
  1699.            && CONSTANT_ADDRESS_P (XEXP (dest, 0))))
  1700.     {
  1701.       rtx xoperands[2];
  1702.       char *split_template;
  1703.       xoperands[0] = dest;
  1704.       xoperands[1] = src;
  1705.  
  1706.       /* Output the `sethi' insn.  */
  1707.       if (GET_CODE (src) == MEM)
  1708.     {
  1709.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  1710.          && cc_prev_status.mdep == XEXP (operands[1], 0)))
  1711.         output_asm_insn ("sethi %%hi(%m1),%%g1", xoperands);
  1712.       split_template = "ld [%%g1+%%lo(%m1)],%0";
  1713.     }
  1714.       else
  1715.     {
  1716.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  1717.          && cc_prev_status.mdep == XEXP (operands[0], 0)))
  1718.         output_asm_insn ("sethi %%hi(%m0),%%g1", xoperands);
  1719.       split_template = "st %r1,[%%g1+%%lo(%m0)]";
  1720.     }
  1721.  
  1722.       /* Output the branch instruction next.  */
  1723.       output_asm_insn (template, operands);
  1724.  
  1725.       /* Now output the load or store.
  1726.      No need to do a CC_STATUS_INIT, because we are branching anyway.  */
  1727.       output_asm_insn (split_template, xoperands);
  1728.     }
  1729.   else
  1730.     {
  1731.       extern char *insn_template[];
  1732.       extern char *(*insn_outfun[])();
  1733.       int insn_code_number;
  1734.       rtx pat = gen_rtx (SET, VOIDmode, dest, src);
  1735.       rtx delay_insn = gen_rtx (INSN, VOIDmode, 0, 0, 0, pat, -1, 0, 0);
  1736.       int i;
  1737.       extern rtx alter_subreg();
  1738.       extern int insn_n_operands[];
  1739.  
  1740.       /* Output the branch instruction first.  */
  1741.       output_asm_insn (template, operands);
  1742.  
  1743.       /* Now recognize the insn which we put in its delay slot.
  1744.      We must do this after outputing the branch insn,
  1745.      since operands may just be a pointer to `recog_operand'.  */
  1746.       insn_code_number = recog (pat, delay_insn);
  1747.       if (insn_code_number == -1)
  1748.     abort ();
  1749.  
  1750.       for (i = 0; i < insn_n_operands[insn_code_number]; i++)
  1751.     {
  1752.       if (GET_CODE (recog_operand[i]) == SUBREG)
  1753.         recog_operand[i] = alter_subreg (recog_operand[i]);
  1754.     }
  1755.  
  1756.       /* Now get the template for what this insn would
  1757.      have been, without the branch.  Its operands are
  1758.      exactly the same as they would be, so we don't
  1759.      need to do an insn_extract.  */
  1760.       template = insn_template[insn_code_number];
  1761.       if (template == 0)
  1762.     template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);
  1763.       output_asm_insn (template, recog_operand);
  1764.     }
  1765.   CC_STATUS_INIT;
  1766.   return "";
  1767. }
  1768.  
  1769. /* Output a newly constructed insn DELAY_INSN.  */
  1770. char *
  1771. output_delay_insn (delay_insn)
  1772.      rtx delay_insn;
  1773. {
  1774.   char *template;
  1775.   extern rtx recog_operand[];
  1776.   extern char call_used_regs[];
  1777.   extern char *insn_template[];
  1778.   extern int insn_n_operands[];
  1779.   extern char *(*insn_outfun[])();
  1780.   extern rtx alter_subreg();
  1781.   int insn_code_number;
  1782.   extern int insn_n_operands[];
  1783.   int i;
  1784.  
  1785.   /* Now recognize the insn which we put in its delay slot.
  1786.      We must do this after outputing the branch insn,
  1787.      since operands may just be a pointer to `recog_operand'.  */
  1788.   insn_code_number = recog_memoized (delay_insn);
  1789.   if (insn_code_number == -1)
  1790.     abort ();
  1791.  
  1792.   /* Extract the operands of this delay insn.  */
  1793.   INSN_CODE (delay_insn) = insn_code_number;
  1794.   insn_extract (delay_insn);
  1795.  
  1796.   /* It is possible that this insn has not been properly scaned by final
  1797.      yet.  If this insn's operands don't appear in the peephole's
  1798.      actual operands, then they won't be fixed up by final, so we
  1799.      make sure they get fixed up here.  -- This is a kludge.  */
  1800.   for (i = 0; i < insn_n_operands[insn_code_number]; i++)
  1801.     {
  1802.       if (GET_CODE (recog_operand[i]) == SUBREG)
  1803.     recog_operand[i] = alter_subreg (recog_operand[i]);
  1804.     }
  1805.  
  1806. #ifdef REGISTER_CONSTRAINTS
  1807.   if (! constrain_operands (insn_code_number))
  1808.     abort ();
  1809. #endif
  1810.  
  1811.   cc_prev_status = cc_status;
  1812.  
  1813.   /* Update `cc_status' for this instruction.
  1814.      The instruction's output routine may change it further.
  1815.      If the output routine for a jump insn needs to depend
  1816.      on the cc status, it should look at cc_prev_status.  */
  1817.  
  1818.   NOTICE_UPDATE_CC (PATTERN (delay_insn), delay_insn);
  1819.  
  1820.   /* Now get the template for what this insn would
  1821.      have been, without the branch.  */
  1822.  
  1823.   template = insn_template[insn_code_number];
  1824.   if (template == 0)
  1825.     template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);
  1826.   output_asm_insn (template, recog_operand);
  1827.   return "";
  1828. }
  1829.  
  1830. /* Output the insn HEAD, keeping OPERANDS protected (wherever they are).
  1831.    HEAD comes from the target of some branch, so before we output it,
  1832.    we delete it from the target, lest we execute it twice.  The caller
  1833.    of this function promises that such code motion is permissable.  */
  1834. char *
  1835. output_eager_then_insn (head, operands)
  1836.      rtx head;
  1837.      rtx *operands;
  1838. {
  1839.   extern rtx alter_subreg ();
  1840.   extern int insn_n_operands[];
  1841.   extern rtx recog_operand[];
  1842.   rtx xoperands[MAX_RECOG_OPERANDS];
  1843.   int insn_code_number, i, nbytes;
  1844.   rtx nhead;
  1845.  
  1846.   /* Micro-hack: run peephole on head if it looks like a good idea.
  1847.      Right now there's only one such case worth doing...
  1848.  
  1849.      This could be made smarter if the peephole for ``2-insn combine''
  1850.      were also made smarter.  */
  1851.   if (GET_CODE (PATTERN (head)) == SET
  1852.       && REG_P (SET_SRC (PATTERN (head)))
  1853.       && REG_P (SET_DEST (PATTERN (head)))
  1854.       && (nhead = next_real_insn_no_labels (head))
  1855.       && GET_CODE (nhead) == INSN
  1856.       && GET_CODE (PATTERN (nhead)) == SET
  1857.       && GET_CODE (SET_DEST (PATTERN (nhead))) == CC0
  1858.       && (SET_SRC (PATTERN (nhead)) == SET_SRC (PATTERN (head))
  1859.       || SET_SRC (PATTERN (nhead)) == SET_DEST (PATTERN (head))))
  1860.     /* Something's wrong if this does not fly.  */
  1861.     if (! peephole (head))
  1862.       abort ();
  1863.  
  1864.   /* Save our contents of `operands', since output_delay_insn sets them.  */
  1865.   insn_code_number = recog_memoized (head);
  1866.   nbytes = insn_n_operands[insn_code_number] * sizeof (rtx);
  1867.   bcopy (operands, xoperands, nbytes);
  1868.  
  1869.   /* Output the delay insn, and prevent duplication later.  */
  1870.   delete_insn (head);
  1871.   output_delay_insn (head);
  1872.  
  1873.   /* Restore this insn's operands.  */
  1874.   bcopy (xoperands, operands, nbytes);
  1875. }
  1876.  
  1877. /* Return the next INSN, CALL_INSN or JUMP_INSN after LABEL;
  1878.    or 0, if there is none.  Also return 0 if we cross a label.  */
  1879.  
  1880. rtx
  1881. next_real_insn_no_labels (label)
  1882.      rtx label;
  1883. {
  1884.   register rtx insn = NEXT_INSN (label);
  1885.   register RTX_CODE code;
  1886.  
  1887.   while (insn)
  1888.     {
  1889.       code = GET_CODE (insn);
  1890.       if (code == INSN)
  1891.     {
  1892.       if (GET_CODE (PATTERN (insn)) != CLOBBER
  1893.           && GET_CODE (PATTERN (insn)) != USE)
  1894.         return insn;
  1895.     }
  1896.       if (code == CALL_INSN || code == JUMP_INSN)
  1897.     return insn;
  1898.       if (code == CODE_LABEL)
  1899.     return 0;
  1900.       insn = NEXT_INSN (insn);
  1901.     }
  1902.  
  1903.   return 0;
  1904. }
  1905.  
  1906. int
  1907. operands_satisfy_eager_branch_peephole (operands, conditional)
  1908.      rtx *operands;
  1909.      int conditional;
  1910. {
  1911.   rtx label;
  1912.  
  1913.   if (conditional)
  1914.     {
  1915.       if (GET_CODE (operands[0]) != IF_THEN_ELSE)
  1916.     return 0;
  1917.  
  1918.       if (GET_CODE (XEXP (operands[0], 1)) == LABEL_REF)
  1919.     label = XEXP (XEXP (operands[0], 1), 0);
  1920.       else if (GET_CODE (XEXP (operands[0], 2)) == LABEL_REF)
  1921.     label = XEXP (XEXP (operands[0], 2), 0);
  1922.       else return 0;
  1923.     }
  1924.   else
  1925.     {
  1926.       label = operands[0];
  1927.     }
  1928.  
  1929.   if (LABEL_NUSES (label) == 1)
  1930.     {
  1931.       rtx prev = PREV_INSN (label);
  1932.       while (prev && GET_CODE (prev) == NOTE)
  1933.     prev = PREV_INSN (prev);
  1934.       if (prev == 0
  1935.       || GET_CODE (prev) == BARRIER)
  1936.     {
  1937.       rtx head = next_real_insn_no_labels (label);
  1938.  
  1939.       if (head
  1940.           && ! INSN_DELETED_P (head)
  1941.           && GET_CODE (head) == INSN
  1942.           && GET_CODE (PATTERN (head)) == SET
  1943.           && strict_single_insn_op_p (SET_SRC (PATTERN (head)),
  1944.                       GET_MODE (SET_DEST (PATTERN (head))))
  1945.           && strict_single_insn_op_p (SET_DEST (PATTERN (head)),
  1946.                       GET_MODE (SET_DEST (PATTERN (head)))))
  1947.         {
  1948.           if (conditional == 2)
  1949.         return (GET_CODE (operands[1]) != PC
  1950.             && safe_insn_src_p (operands[2], VOIDmode)
  1951.             && strict_single_insn_op_p (operands[2], VOIDmode)
  1952.             && operand_clobbered_before_used_after (operands[1], label));
  1953.           return 1;
  1954.         }
  1955.     }
  1956.     }
  1957.  
  1958.   if (conditional == 1
  1959.       && GET_CODE (operands[1]) != PC
  1960.       && safe_insn_src_p (operands[2], VOIDmode)
  1961.       && strict_single_insn_op_p (operands[2], VOIDmode)
  1962.       && operand_clobbered_before_used_after (operands[1], label))
  1963.     return 1;
  1964.  
  1965.   return 0;
  1966. }
  1967.  
  1968.